home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\TRANSLAT.C < prev    next >
C/C++ Source or Header  |  1994-12-28  |  10KB  |  434 lines

  1. /*
  2.  * translat.c:  Stuff for handling character translation tables
  3.  * and a digraph entry facility.  Support an international IRC!
  4.  *
  5.  * I listen to Sex Pistols, so I assume everyone in this world,
  6.  * and more specifically, all servers, are using ISO 8859/1
  7.  * (Latin-1).  And in case of doubt, please consult Jarkko 'Wiz'
  8.  * Oikarinen's document "Internet Relay Chat Protocol" (doc/Comms
  9.  * in the ircd package), paragraph 2.2.  Besides, all of the sane
  10.  * world has already converted to this set.  (X-Windows, Digital,
  11.  * MS-Windows, etc.)
  12.  * If someone please would forward me some documentation on other
  13.  * international sets, like 8859/2 - 8859/10 etc, please do so!
  14.  * Moreover, feedback on the tables in the definition files would
  15.  * be greatly appreciated!
  16.  * Another idea, to be implemented some beautiful day, would be
  17.  * to add transliteration of the Kanji/Katakana sets used in
  18.  * the far east.  8-)
  19.  * Tomten <tomten@solace.hsh.se> / <tomten@lysator.liu.se>
  20.  */
  21.  
  22. #ifndef lint
  23. static    char    rcsid[] = "@(#)$Id: translat.c,v 1.6 1994/07/02 02:32:13 mrg Stab $";
  24. #endif
  25.  
  26. #include "irc.h"
  27.  
  28. #include "vars.h"
  29. #include "translat.h"
  30. #include "ircaux.h"
  31. #include "window.h"
  32. #include "screen.h"
  33. #include "output.h"
  34.  
  35. #if defined(__STDC__) || defined(__cplusplus)
  36. static    unsigned char    my_getarg(char **args);
  37. #else
  38. static    unsigned char    my_getarg();
  39. #endif
  40.  
  41. /* Globals */
  42. unsigned char    transToClient[256];    /* Server to client translation. */
  43. unsigned char    transFromClient[256];  /* Client to server translation. */
  44. char    translation = 0;    /* 0 for transparent (no) translation. */
  45. char    digraph_changed = 0;
  46.  
  47. /*
  48.  * dig_table_lo[] and dig_table_hi[] contain the character pair that
  49.  * will result in the digraph in dig_table_di[].  To avoid searching
  50.  * both tables, I take the lower character of the pair, and only
  51.  * search dig_table_lo[].  Thus, dig_table_lo[] must always contain
  52.  * the lower character of the pair.
  53.  *
  54.  * The digraph tables are based on those in the excellent editor Elvis,
  55.  * with some additions for those, like me, who are used to VT320 or
  56.  * VT420 terminals.
  57.  */
  58.  
  59. #define    DiLo(x)    x,
  60. #define    DiHi(x)
  61. #define    DiDi(x)
  62.  
  63. /*
  64.  * Digraph tables.  Note that, when adding a new digraph, the character
  65.  * of the pair with the lowest value, *must* be in the DiLo column.
  66.  * The higher of the pair goes in DiHi, and the digraph itself in DiDi.
  67.  */
  68.  
  69. unsigned char    dig_table_lo[DIG_TABLE_SIZE] =
  70. {
  71. #include "digraph.inc"
  72.     0
  73. };
  74.  
  75.  
  76. #undef    DiLo
  77. #undef    DiHi
  78. #undef    DiDi
  79. #define    DiLo(x)
  80. #define    DiHi(x)    x,
  81. #define    DiDi(x)
  82.  
  83. unsigned char    dig_table_hi[DIG_TABLE_SIZE] =
  84. {
  85. #include "digraph.inc"
  86.     0
  87. };
  88.  
  89.  
  90. #undef    DiLo
  91. #undef    DiHi
  92. #undef    DiDi
  93. #define    DiLo(x)
  94. #define    DiHi(x)
  95. #define    DiDi(x)    x,
  96.  
  97. unsigned char    dig_table_di[DIG_TABLE_SIZE] =
  98. {
  99. #include "digraph.inc"
  100.     0
  101. };
  102.  
  103.  
  104. /*
  105.  * enter_digraph:  The BIND function ENTER_DIGRAPH.
  106.  */
  107. #if defined(__STDC__) || defined(__cplusplus)
  108. void    enter_digraph(unsigned char key, char *ptr)
  109. #else
  110. void    enter_digraph(key, str)
  111. unsigned char    key;
  112. char    *str;
  113. #endif
  114. {
  115.     current_screen->digraph_hit = 1;  /* Just stuff away first character. */
  116. }
  117.  
  118. /*
  119.  * get_digraph:  Called by edit_char() when a digraph entry is activated.
  120.  * Looks up a digraph given char c1 and the global char
  121.  * current_screen->digraph_hit.
  122.  */
  123. #if defined(__STDC__) || defined(__cplusplus)
  124. unsigned char    get_digraph(unsigned char c1)
  125. #else
  126. unsigned char    get_digraph(c1)
  127. unsigned char    c1;
  128. #endif
  129. {
  130.     int    i = 0;
  131.     unsigned char    c,
  132.         c2 = current_screen->digraph_first;
  133.  
  134.     current_screen->digraph_hit = 0;
  135.     if (c1 > c2)    /* Make sure we have the lowest one in c1. */
  136.         c = c1,    c1 = c2, c2 = c;
  137.     while (dig_table_lo[i])
  138.     {    /* Find digraph and return it. */
  139.         if ((dig_table_lo[i] == c1) && (dig_table_hi[i] == c2))
  140.             return dig_table_di[i];
  141.         i++;
  142.     }
  143.     return 0;        /* Failed lookup. */
  144. }
  145.  
  146.  
  147. /*
  148.  * set_translation:  Called when the TRANSLATION variable is SET.
  149.  * Attempts to load a new translation table.
  150.  */
  151. #if defined(__STDC__) || defined(__cplusplus)
  152. void    set_translation(char *tablename)
  153. #else
  154. void    set_translation(tablename)
  155. char    *tablename;
  156. #endif
  157. {
  158.     FILE    *table;
  159.     unsigned char    temp_table[512];
  160.     char    *filename = (char *) 0;
  161.     int    inputs[8];
  162.     int    j,
  163.         c = 0;
  164.  
  165.     tablename = upper(tablename);
  166.  
  167.     /* Check for transparent mode; ISO-8859/1, Latin-1 */
  168.     if (!strcmp("LATIN_1", tablename))
  169.     {
  170.         translation = 0;
  171.         return;
  172.     }
  173.  
  174.     /* Else try loading the translation table from disk. */
  175.     malloc_strcpy(&filename, TRANSLATION_PATH);
  176.     malloc_strcat(&filename, tablename);
  177.     if ( !(table = fopen(filename, "r")) )
  178.     {
  179.         say("Cannot open character table definition \"%s\" !",
  180.             tablename);
  181.         set_string_var(TRANSLATION_VAR, (char *) 0);
  182.         new_free(&filename);
  183.         return;
  184.     }
  185.  
  186.     /* Any problems in the translation tables between hosts are
  187.      * almost certain to be caused here.
  188.      * many scanf implementations do not work as defined. In particular,
  189.      * scanf should ignore white space including new lines (many stop
  190.      * at the new line character, hence the fgets and sscanf workaround),
  191.      * many fail to read 0xab as a hexadecimal number (failing on the
  192.      * x) despite the 0x being defined as optionally existing on input,
  193.      * and others zero out all the output variables if there is trailing
  194.      * non white space in the format string which doesn't appear on the
  195.      * input. Overall, the standard I/O libraries have a tendancy not
  196.      * to be very standard.
  197.      */
  198.  
  199.     while (fgets(buffer, 80, table))
  200.     {
  201.         sscanf(buffer, "0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x,0x%x",
  202.             inputs+0, inputs+1, inputs+2, inputs+3,
  203.             inputs+4, inputs+5, inputs+6, inputs+7);
  204.         for (j = 0; j<8; j++)
  205.             temp_table[c++] = (unsigned char) inputs[j];
  206.     }
  207.     fclose(table);
  208.     new_free(&filename);
  209.     if (c == 512)
  210.     {
  211.         for (c = 0; c <= 255; c++)
  212.         {
  213.             transToClient[c] = temp_table[c];
  214.             transFromClient[c] = temp_table[c | 256];
  215.         }
  216.         translation = 1;
  217.     }
  218.     else
  219.     {
  220.         say("Error loading translation table \"%s\" !", tablename);
  221.         set_string_var(TRANSLATION_VAR, (char *) 0);
  222.     }
  223. }
  224.  
  225. /*
  226.  * digraph:  The /DIGRAPH command with facilities.
  227.  * This routine is *NOT* finished yet.
  228.  */
  229.  
  230. #if defined(__STDC__) || defined(__cplusplus)
  231. void    digraph(char *command, char *args)
  232. #else
  233. void    digraph(command, args)
  234. char    *command,
  235. *args;
  236. #endif
  237. {
  238.     char    *arg;
  239.     u_char    c1,
  240.         c2 = '\0',
  241.         c3 = '\0';
  242.     int    len,
  243.         i;
  244.  
  245.     if ((arg = next_arg(args, &args)) && (*arg == '-'))
  246.     {
  247.         arg++;
  248.         if ((len = strlen(arg)) == 0)
  249.         {
  250.             say("Unknown or missing flag.");
  251.             return;
  252.         }
  253.         if (my_strnicmp(arg, "add", len) == 0)
  254.         {
  255.             /*
  256.              * Add a digraph to the table.
  257.              * I *know*.  This *is* a kludge.
  258.              */
  259.             if ((i = strlen((char *)dig_table_lo)) ==
  260.                     DIG_TABLE_SIZE - 1)
  261.                 say("Sorry, digraph table full.");
  262.             else
  263.             {
  264.                 while ((c1 = my_getarg(&args)) &&
  265.                     (c2 = my_getarg(&args)) &&
  266.                     (c3 = my_getarg(&args)))
  267.                 {
  268.                     /* Pass c1 to get_digraph() */
  269.                     current_screen->digraph_first = c1;        
  270.                     if (get_digraph(c2) == 0)
  271.                     {
  272.                         dig_table_di[i] = c3;
  273.                         /* Make sure c1 <= c2 */
  274.                         if (c1 > c2)
  275.                             c3 = c1, c1 = c2, c2 = c3;
  276.                         dig_table_lo[i] = c1;
  277.                         dig_table_hi[i] = c2;
  278.                         i++;
  279.                         dig_table_lo[i] =
  280.                             dig_table_hi[i] =
  281.                              dig_table_di[i] =
  282.                             (unsigned char) 0;
  283.                         digraph_changed = 1;
  284.                         say("Digraph added to table.");
  285.                     }
  286.                     else
  287.                     {
  288.                 say("Digraph already defined in table.");
  289.                 break;
  290.                     }
  291.                 }
  292.                 if (!c2 || !c3)
  293.                     say("Unknown or missing argument.");
  294.             }
  295.  
  296.         }
  297.         else if (my_strnicmp(arg, "remove", len) == 0)
  298.         {
  299.  
  300.             /* Remove a digraph from the table. */
  301.             if ((i = strlen((char *)dig_table_lo)) == 0)
  302.                 say("Digraph table is already empty.");
  303.             else
  304.             {
  305.                 if ((c1 = my_getarg(&args)) &&
  306.                         (c2 = my_getarg(&args)))
  307.                 {
  308.                     i = 0;
  309.                     if (c1 > c2)
  310.                         c3 = c1, c1 = c2, c2 = c3;
  311.                     while (dig_table_lo[i])
  312.                     {
  313.                         if ((dig_table_lo[i] == c1) &&
  314.                             (dig_table_hi[i] == c2))
  315.                     /*
  316.                      * strcpy() is not guaranteed for
  317.                      * overlapping copying, but this one
  318.                      * is high -> low. Ought to be fixed.
  319.                      */
  320.     /* re-indent this block - phone, jan 1993. */
  321.                 {
  322.                     strcpy(((char *)dig_table_lo + i),
  323.                         (char *)(dig_table_lo + (i + 1)));
  324.                     strcpy((char *)(dig_table_hi + i),
  325.                         (char *)(dig_table_hi + (i + 1)));
  326.                     strcpy((char *)(dig_table_di + i),
  327.                         (char *)(dig_table_di + (i + 1)));
  328.                     digraph_changed = 1;
  329.                     put_it("Digraph removed from table.");
  330.                     return;
  331.                 }
  332.     /* much better */
  333.                         i++;
  334.                     }
  335.                     say("Digraph not found.");
  336.                 }
  337.             }
  338.         }
  339.         else if (my_strnicmp(arg, "clear", len) == 0)
  340.         {
  341.  
  342.             /* Clear digraph table. */
  343.             dig_table_lo[0] = dig_table_hi[0] = dig_table_di[0] =
  344.                 (unsigned char) 0;
  345.             digraph_changed = 1;
  346.             say("Digraph table cleared.");
  347.  
  348.         }
  349.         else
  350.             say("Unknown flag.");
  351.     }
  352.     else
  353.     {
  354.  
  355.         /* Display digraph table. */
  356.         char    buffer1[8];
  357.         char    buffer2[192];
  358.  
  359.         say("Digraph table:");
  360.         buffer2[0] = (char) 0;
  361.         i = 0;
  362.         while(dig_table_lo[i])
  363.         {
  364.             sprintf(buffer1, "%c%c %c   ", dig_table_lo[i],
  365.                 dig_table_hi[i], dig_table_di[i]);
  366.             strcat(buffer2, buffer1);
  367.             if ((++i % 10) == 0)
  368.             {
  369.                 put_it(buffer2);
  370.                 buffer2[0] = (char) 0;
  371.             }
  372.         }
  373.         if (buffer2[0])
  374.             put_it(buffer2);
  375.         sprintf(buffer2, "%d digraphs listed.", i);
  376.         say(buffer2);
  377.     }
  378. }
  379.  
  380. static    unsigned char
  381. #if defined(__STDC__) || defined(__cplusplus)
  382. my_getarg(char **args)
  383. #else
  384. my_getarg(args)
  385.     char    **args;
  386. #endif
  387. {
  388.     unsigned char *arg;
  389.  
  390.     arg = (unsigned char *)next_arg(*args, args);
  391.     if (!args || !*args)
  392.         return '\0';
  393.     /* Don't trust isdigit() with 8 bits. */
  394.     if ((*arg <= '9') && (*arg >= '0'))
  395.     {
  396.         unsigned char i = *arg & 0x0f;
  397.         while ( *(++arg) )
  398.             i = (i * 10) + (*arg & 0x0f);
  399.         return i;
  400.     }
  401.     else if ( (*arg == '!') && (*(arg + 1)) )
  402.         return *(arg + 1) | 0x80;
  403.     return *arg;
  404. }
  405.  
  406. #if defined(__STDC__) || defined(__cplusplus)
  407. void    save_digraphs(FILE *fp)
  408. #else
  409. void    save_digraphs(fp)
  410. FILE    *fp;
  411. #endif
  412. {
  413.     if (digraph_changed)
  414.     {
  415.  
  416.         int    i = 0;
  417.         char    *command = "\nDIGRAPH -ADD ";
  418.  
  419.         fprintf(fp, "DIGRAPH -CLEAR");
  420.         fprintf(fp, command);
  421.         while(1)
  422.         {
  423.             fprintf(fp, "%d %d %d  ", dig_table_lo[i],
  424.                 dig_table_hi[i], dig_table_di[i]);
  425.             if (!dig_table_lo[++i])
  426.                 break;
  427.             if (!(i % 5))
  428.                 fprintf(fp, command);
  429.         }
  430.         fputc('\n', fp);
  431.  
  432.     }
  433. }
  434.